package com.GB26875_3_2011.codec;

import com.GB26875_3_2011.common.GB26875Constant;
import com.GB26875_3_2011.model.GB26875Message;
import com.GB26875_3_2011.util.ByteUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @author 蒋仕国
 * @projectName GB26875_3_211
 * @ClassName MessageEncoder
 * @date 2025-01-13 10:26
 * @Description: TODO []
 */
@Slf4j
@ChannelHandler.Sharable
public class MessageEncoder extends MessageToByteEncoder<GB26875Message> {
    /**
     * Encode a message into a {@link ByteBuf}. This method will be called for each written message that can be handled
     * by this encoder.
     * @param ctx the {@link ChannelHandlerContext} which this {@link MessageToByteEncoder} belongs to
     * @param msg the message to encode
     * @param poolBuffer the {@link ByteBuf} into which the encoded message will be written
     */
    @Override
    protected void encode(ChannelHandlerContext ctx, GB26875Message msg, ByteBuf poolBuffer) {
        // 1. 流水号ID
        poolBuffer.writeShortLE(msg.getFlowId());
        // 2. 版本号ID
        poolBuffer.writeBytes(ByteUtils.hexStr2Bytes(msg.getVersionHex()));
        // 3. 时间标签
        String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern(GB26875Constant.MESSAGE_DATA_FORMAT));
        poolBuffer.writeBytes(ByteUtils.hexStr2Bytes(format));
        // 4. 源地址
        poolBuffer.writeBytes(ByteUtils.hexStr2Bytes(msg.getSourceAddressHex()));
        // 5. 目的地址
        poolBuffer.writeBytes(ByteUtils.hexStr2Bytes(msg.getDestinationAddressHex()));
        // 6. 消息体长度
        if(msg.getMessageBody() != null) {
            poolBuffer.writeShortLE(msg.getMessageBody().length + 2);
        } else {
            poolBuffer.writeShortLE(0);
        }
        // 7. 命令
        poolBuffer.writeByte(msg.getCommandType().getCode());
        // 8. 消息体
        if(msg.getMessageBody() != null && msg.getMessageBody().length > 0) {
            // 8.1 指令类型
            poolBuffer.writeByte(msg.getCommandType().getCode());
            // 8.2 数据单元类型
            poolBuffer.writeByte(msg.getDataUnitType().getCode());
            // 8.3 具体数据
            poolBuffer.writeBytes(msg.getMessageBody());
        }
        // 9. 校验码 【重新计算】
        String messageHex = ByteBufUtil.hexDump(poolBuffer);
        poolBuffer.writeByte(calculateCheckSum(messageHex));
    }

    private static byte calculateCheckSum(String hex) {
        byte[] bytes = ByteUtils.hexStr2Bytes(hex);
        int sum = 0;
        for (byte b : bytes) {
            sum += b;
        }
        return (byte) (sum & 0xff);
    }


}
